from markupsafe import Markup
from itertools import groupby

from odoo import fields, models, api, _
from odoo.exceptions import UserError


class MrpBom(models.Model):
    _inherit = 'mrp.bom'

    pcs_panel_ratio = fields.Float(string='pcs panel ratio', compute='_compute_panel_pcs_ratio')
    panel_pcs_ratio = fields.Float(string='panel pcs ratio', compute='_compute_panel_pcs_ratio')

    def _compute_panel_pcs_ratio(self):
        for rec in self:
            uom_value_ids = rec.product_tmpl_id.uom_value_ids
            pcs_uom_rec = uom_value_ids.filtered(lambda x: x.uom_id.code == 'PCS')
            panel_uom_rec = uom_value_ids.filtered(lambda x: x.uom_id.code == 'PANEL')

            if not pcs_uom_rec or not panel_uom_rec:
                rec.pcs_panel_ratio = 0
                rec.panel_pcs_ratio = 0
                continue

            pcs_uom_value = pcs_uom_rec[0].uom_value
            panel_uom_value = panel_uom_rec[0].uom_value

            if pcs_uom_value and panel_uom_value:
                rec.pcs_panel_ratio = pcs_uom_value / panel_uom_value
                rec.panel_pcs_ratio = panel_uom_value / pcs_uom_value
            else:
                rec.pcs_panel_ratio = 0
                rec.panel_pcs_ratio = 0

    def action_open_mps_view(self):
        pass

    @api.constrains('product_tmpl_id')
    def constrains_product_tmpl_id_one(self):
        for rec in self:
            if self.search_count([('product_tmpl_id', '=', rec.product_tmpl_id.id)]) > 1:
                raise UserError(_('A product can only have one BOM, %s', rec.product_tmpl_id.name))


class MrpBomLine(models.Model):
    _inherit = 'mrp.bom.line'

    product_qty = fields.Float(
        string='PCS quantity', digits=(10, 6),
        compute='_compute_product_qty',
        inverse='_inverse_product_qty',
        store=True)
    panel_qty = fields.Float(string='PANEL quantity', digits=(10, 6))

    @api.depends('panel_qty')
    @api.constrains('panel_qty')
    def _compute_product_qty(self):
        for rec in self:
            if rec.bom_id.pcs_panel_ratio:
                rec.product_qty = rec.panel_qty * rec.bom_id.pcs_panel_ratio

    def _inverse_product_qty(self):
        for rec in self:
            if rec.bom_id.pcs_panel_ratio:
                rec.panel_qty = rec.product_qty * rec.bom_id.panel_pcs_ratio

    def unlink(self):
        for bom_id, g in groupby(self.sorted(lambda x: x.bom_id.id), lambda x: x.bom_id):
            bom_lines = self.env['mrp.bom.line'].concat(*g)
            msg = Markup("<b>%s</b><ul>") % _("The bom line product has been deleted.")
            for line in bom_lines:
                msg += Markup("<li> %s <br/>") % line.product_id.display_name
            msg += Markup("</ul>")
            bom_id.message_post(body=msg)
        return super().unlink()

    def write(self, vals):
        if 'product_id' in vals:
            self._update_product_message(vals)
        return super().write(vals)

    def _update_product_message(self, vals):
        bom_ids = self.mapped('bom_id')
        if 'product_id' not in vals:
            return
        new_product_id = self.env['product.product'].browse(int(vals['product_id']))
        for bom in bom_ids:
            bom_line_ids = self.filtered(lambda x: x.bom_id == bom)

            msg = Markup("<b>%s</b><ul>") % _("The bom line product has been updated.")
            for line in bom_line_ids:
                if new_product_id == line.product_id:
                    continue

                msg += Markup("<li> %s -> %s <br/>") % (line.product_id.display_name, new_product_id.display_name)

            msg += Markup("</ul>")
            bom.message_post(body=msg)


